/******************************************************************************\
    Data.cpp contains implementations of plugin commands.
    It's used with acm server plugins. See DllMain.cpp for details.
    Copyright (C) 2008  Victor Vinogradov (fly3333@gmail.com)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
\******************************************************************************/

#include <windows.h>
#include ".\Data.h"
#include <cstring>
#include "Auxiliary.h"
#include ".\Post.h"
using namespace std;

bool SetProxyPort( unsigned short port )
{
	Port = port;
	return true;
}

bool GetTitleLength( unsigned long *title_length )
{
	cLocker locker( AboutCriticalSection );
	*title_length = ( unsigned long )strlen( Title );
	return true;
}

bool GetTitle( char *title )
{
	cLocker locker( AboutCriticalSection );
	strcpy( title, Title );
	return true;
}

bool GetCommentLength( unsigned long *comment_length )
{
	cLocker locker( AboutCriticalSection );
	*comment_length = ( unsigned long )strlen( Comment );
	return true;
}

bool GetComment( char *comment )
{
	cLocker locker( AboutCriticalSection );
	strcpy( comment, Comment );
	return true;
}

bool GetVariablesCount( unsigned long *variables_count )
{
	cLocker locker( VariablesCriticalSection );
	*variables_count = VariablesCount;
	return true;
}

//bool GetVariableNameLength( unsigned long variable_id, unsigned long *variable_name_length )
//{
//	cLocker locker( VariablesCriticalSection );
//	if( VariablesCount <= variable_id )
//		return false;
//	*variable_name_length = strlen( VariableName[ variable_id ] );
//	return true;
//}
//
//bool GetVariableName( unsigned long variable_id, char *variable_name )
//{
//	cLocker locker( VariablesCriticalSection );
//	if( VariablesCount <= variable_id )
//		return false;
//	strcpy( variable_name, VariableName[ variable_id ] );
//	return true;
//}

bool SetVariableValue( unsigned long variable_id, char *variable_value )
{
	cLocker locker( VariablesCriticalSection );
	if( VariablesCount <= variable_id )
		return false;
	VariableValue[ variable_id ] = variable_value;
	return true;
}

bool GetProblemsCount( unsigned long *problems_count )
{
	if( !LoadProblems() )
		return false;
	cLocker locker( ProblemsCriticalSection );
	*problems_count = ( unsigned long )Problem.size();
	return true;
}

bool GetProblemsIds( unsigned long *problem_id )
{
	if( !LoadProblems() )
		return false;
	cLocker locker( ProblemsCriticalSection );
	for( int i = 0; i < ( int )Problem.size(); ++i )
	{
		problem_id[ i ] = Problem[ i ].Id;
	}
	return true;
}

bool GetProblemHeaderLength( unsigned long problem_id, unsigned long *problem_header_length )
{
	if( !LoadProblems() )
		return false;
	cLocker locker( ProblemsCriticalSection );
	map< unsigned long, unsigned long >::const_iterator problem_index_iterator = ProblemIndex.find( problem_id );
	if( problem_index_iterator == ProblemIndex.end() )
		return false;
	*problem_header_length = ( unsigned long )Problem[ problem_index_iterator->second ].Header.length();
	return true;
}

bool GetProblemHeader( unsigned long problem_id, char *problem_header )
{
	if( !LoadProblems() )
		return false;
	cLocker locker( ProblemsCriticalSection );
	map< unsigned long, unsigned long >::const_iterator problem_index_iterator = ProblemIndex.find( problem_id );
	if( problem_index_iterator == ProblemIndex.end() )
		return false;
	strcpy( problem_header, Problem[ problem_index_iterator->second ].Header.c_str() );
	return true;
}

bool GetProblemBodyLength( unsigned long problem_id, unsigned long *problem_body_length )
{
	if( !LoadProblems() )
		return false;
	cLocker locker( ProblemsCriticalSection );
	map< unsigned long, unsigned long >::const_iterator problem_index_iterator = ProblemIndex.find( problem_id );
	if( problem_index_iterator == ProblemIndex.end() )
		return false;
	if( !Problem[ problem_index_iterator->second ].Load() )
		return false;
	*problem_body_length = ( unsigned long )Problem[ problem_index_iterator->second ].Body.length();
	return true;
}

bool GetProblemBody( unsigned long problem_id, char *problem_body )
{
	if( !LoadProblems() )
		return false;
	cLocker locker( ProblemsCriticalSection );
	map< unsigned long, unsigned long >::const_iterator problem_index_iterator = ProblemIndex.find( problem_id );
	if( problem_index_iterator == ProblemIndex.end() )
		return false;
	if( !Problem[ problem_index_iterator->second ].Load() )
		return false;
	strcpy( problem_body, Problem[ problem_index_iterator->second ].Body.c_str() );
	return true;
}

bool GetProblemAdditionsCount( unsigned long problem_id, unsigned long *additions_count )
{
	if( !LoadProblems() )
		return false;
	cLocker problems_locker( ProblemsCriticalSection );
	map< unsigned long, unsigned long >::const_iterator problem_index_iterator = ProblemIndex.find( problem_id );
	if( problem_index_iterator == ProblemIndex.end() )
		return false;
	if( !Problem[ problem_index_iterator->second ].Load() )
		return false;
	cLocker additions_locker( AdditionsCriticalSection );
	*additions_count = ( unsigned long )Problem[ problem_index_iterator->second ].AdditionId.size();
	return true;
}

bool GetProblemAdditionsIds( unsigned long problem_id, unsigned long *addition_id )
{
	if( !LoadProblems() )
		return false;
	cLocker problems_locker( ProblemsCriticalSection );
	map< unsigned long, unsigned long >::const_iterator problem_index_iterator = ProblemIndex.find( problem_id );
	if( problem_index_iterator == ProblemIndex.end() )
		return false;
	if( !Problem[ problem_index_iterator->second ].Load() )
		return false;
	cLocker additions_locker( AdditionsCriticalSection );
	for( int i = 0; i < ( int )Problem[ problem_index_iterator->second ].AdditionId.size(); ++i )
	{
		addition_id[ i ] = Problem[ problem_index_iterator->second ].AdditionId[ i ];
	}
	return true;
}

bool GetAdditionNameLength( unsigned long addition_id, unsigned long *addition_name_length )
{
	cLocker locker( AdditionsCriticalSection );
	if( Addition.size() <= addition_id )
		return false;
	*addition_name_length = ( unsigned long )Addition[ addition_id ].Name.length();
	return true;
}

bool GetAdditionName( unsigned long addition_id, char *addition_name )
{
	cLocker locker( AdditionsCriticalSection );
	if( Addition.size() <= addition_id )
		return false;
	strcpy( addition_name, Addition[ addition_id ].Name.c_str() );
	return true;
}

bool GetAdditionDataLength( unsigned long addition_id, unsigned long *addition_data_length )
{
	cLocker locker( AdditionsCriticalSection );
	if( Addition.size() <= addition_id )
		return false;
	*addition_data_length = ( unsigned long )Addition[ addition_id ].Data.size();
	return true;
}

bool GetAdditionData( unsigned long addition_id, char *addition_data )
{
	cLocker locker( AdditionsCriticalSection );
	if( Addition.size() <= addition_id )
		return false;
	memcpy( addition_data, Addition[ addition_id ].Data.data(), Addition[ addition_id ].Data.size() );
	return true;
}

bool GetLanguagesCount( unsigned long *languages_count )
{
	if( !LoadLanguages() )
		return false;
	cLocker locker( LanguagesCriticalSection );
	*languages_count = ( unsigned long )Language.size();
	return true;
}

bool GetLanguagesIds( unsigned long *language_id )
{
	if( !LoadLanguages() )
		return false;
	cLocker locker( LanguagesCriticalSection );
	for( int i = 0; i < ( int )Language.size(); ++i )
	{
		language_id[ i ] = Language[ i ].Id;
	}
	return true;
}

bool GetLanguageTitleLength( unsigned long language_id, unsigned long *language_title_length )
{
	if( !LoadLanguages() )
		return false;
	cLocker locker( LanguagesCriticalSection );
	map< unsigned long, unsigned long >::const_iterator language_index_iterator = LanguageIndex.find( language_id );
	if( language_index_iterator == LanguageIndex.end() )
		return false;
	*language_title_length = ( unsigned long )Language[ language_index_iterator->second ].Title.length();
	return true;
}

bool GetLanguageTitle( unsigned long language_id, char *language_title )
{
	if( !LoadLanguages() )
		return false;
	cLocker locker( LanguagesCriticalSection );
	map< unsigned long, unsigned long >::const_iterator language_index_iterator = LanguageIndex.find( language_id );
	if( language_index_iterator == LanguageIndex.end() )
		return false;
	strcpy( language_title, Language[ language_index_iterator->second ].Title.c_str() );
	return true;
}

bool Submit( sSubmit *submit_data )
{
	if( !LoadProblems() )
		return false;
	if( !LoadLanguages() )
		return false;
	unsigned long problem_index;
	{
		cLocker problems_locker( ProblemsCriticalSection );
		map< unsigned long, unsigned long >::const_iterator problem_index_iterator = ProblemIndex.find( submit_data->ProblemId );
		if( problem_index_iterator == ProblemIndex.end() )
			return false;
		problem_index = problem_index_iterator->second;
	}
	unsigned long language_index;
	{
		cLocker languages_locker( LanguagesCriticalSection );
		map< unsigned long, unsigned long >::const_iterator language_index_iterator = LanguageIndex.find( submit_data->LanguageId );
		if( language_index_iterator == LanguageIndex.end() )
			return false;
		language_index = language_index_iterator->second;
	}
	if( !SubSubmit( problem_index, language_index, string( submit_data->Code, submit_data->CodeLength ), submit_data->Result, submit_data->TestNumber, submit_data->Time, submit_data->Memory ) )
		return false;
	return true;
}

bool GetLastCompilationErrorLength( unsigned long *last_compilation_error_length )
{
	cLocker locker( CompilationErrorCriticalSection );
	*last_compilation_error_length = ( unsigned long )CompilationError[ GetCurrentThreadId() ].length();
	return true;
}

bool GetLastCompilationError( char *last_compilation_error )
{
	cLocker locker( CompilationErrorCriticalSection );
	strcpy( last_compilation_error, CompilationError[ GetCurrentThreadId() ].c_str() );
	return true;
}

bool GetVariablePropertiesLength( unsigned long variable_id, unsigned long *variable_properties_length )
{
	cLocker locker( VariablesCriticalSection );
	if( VariablesCount <= variable_id )
		return false;
	*variable_properties_length = strlen( VariableProperties[ variable_id ] );
	return true;
}

bool GetVariableProperties( unsigned long variable_id, char *variable_properties )
{
	cLocker locker( VariablesCriticalSection );
	if( VariablesCount <= variable_id )
		return false;
	strcpy( variable_properties, VariableProperties[ variable_id ] );
	return true;
}
